﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "gnsslogs_global.h"

#include "GnssLogVariant.h"

#include <ranges>
#include <string_view>

namespace GnssLogs
{
class GNSSLOGS_EXPORT Decoder
{
public:
    template<typename Data>
    std::optional<Data> decode(std::string_view source) const noexcept;

    template<typename Variant>
    std::vector<Variant> decodeLogs(std::string_view logs) const noexcept;

private:
    template<size_t index, typename Variant>
    Variant _decode(std::string_view source) const;
};

template<size_t index, typename Variant>
Variant Decoder::_decode(std::string_view source) const
{
    if constexpr (index >= std::variant_size_v<Variant>)
        throw std::runtime_error("Unknown log");
    else
    {
        using Type = std::variant_alternative_t<index, Variant>;
        if (auto ret = decode<Type>(source); ret)
            return *ret;
        return _decode<index + 1, Variant>(source);
    }
}

template<typename Variant>
std::vector<Variant> Decoder::decodeLogs(std::string_view logs) const noexcept
{
    std::vector<Variant> rets;
    for (auto view : logs | std::views::chunk_by([](char x, char y) { return x != '\n'; }))
    {
        try
        {
            rets.emplace_back(_decode<0, Variant>(std::string_view(view.begin(), view.end())));
        }
        catch (const std::exception&)
        {
            // ignore
        }
    }
    return rets;
}

} // namespace GnssLogs